package demo03_collection

import scala.collection.immutable.HashSet

object Demo02_immutableCollection {

  /**
   * 创建Set
   */
  def createSet() = {
    val set: Set[Int] = Set(2, 6, 1, 8, 4, 2, 4, 1, 1, 8)
    println(set)

    val hashSet: HashSet[Int] = HashSet(6, 4, 5, 3, 2, 6, 4, 5)
    println(hashSet)
  }

  /**
   * 创建Map
   * map.get(key)获取的是value的一元集合的形式
   * map(key) 获取的是value的真正的值
   */
  def createMap() = {

    val map: Map[String, Any] = Map(("name", "tom"), ("age", 20), "gender" -> "男", ("name", "jerry"))
    println(map("name"))

  }

  /**
   * 创建List
   */
  def createList() = {

    val list:List[Int] = List(1,2,3,4,5)
    println(list)
    println(list(3))

  }

  val numList:List[Int] = List(1,2,3,4,5,6,7,8,9,10)

  /**
   * head：集合中的第一个元素
   * tail：除了第一个元素以外，剩余元素组成的集合
   * tails：依次移除第一个元素的结果的集合
   */
  def func1() = {
    println(numList.head)
    println(numList.tail)
    for(num <- numList.tails){
      println(num)
    }
  }

  /**
   * 集合元素的遍历
   */
  def func2() = {

    //第一种方式，直接遍历
    for(num <- numList){
      print(num+" ")
    }
    println()

    //第二种方式，利用索引进行遍历
    for(i <- 0 until numList.length){
      print(numList(i)+" ")
    }
    println()

    //第三种方式，使用null和长度为0判断
    var tempList1 = numList
    while(tempList1!=null && tempList1.size>0){
      print(tempList1.head+" ")
      tempList1 = tempList1.tail
    }
    println()

    //第四种方式，使用List自带的判空的方法
    var tempList2 = numList
    while(!tempList2.isEmpty || tempList2.nonEmpty){
      print(tempList2.head+" ")
      tempList2 = tempList2.tail
    }
    println()

    //第五种方式，使用空List
    var tempList3 = numList
    while(tempList3!=List() || tempList3!=Nil){
      print(tempList3.head+" ")
      tempList3 = tempList3.tail
    }
    println()

    //第六种方式 转换成迭代器
    val numIterator: Iterator[Int] = numList.iterator
    while(numIterator.hasNext){
      print(numIterator.next() + " ")
    }
    println()

    //第七种方式，使用高阶函数
    numList.foreach(print)

  }

  /**
   * 向列表中追加元素
   */
  def func3() = {

    //:: 向列表的左侧追加元素
    val list1 = numList.::(100).::(200)
    println(list1)
    //这种形式也是向列表的左侧追加元素，与点调用::完全等价
    val list2 = 200 :: 100 :: numList
    println(list2)

    //:+ 向列表的右侧追加元素
    val list3 = numList.:+(100).:+(200)
    println(list3)

    //以空列表为基础，实现创建新列表
    val list4 = Nil.:+(100).:+(200)
    println(list4)

    //不管参数是什么，都是以元素的形式进行追加
    val list5 = numList.:+(List(100,200))
    println(list5)
  }

  /**
   * 以列表为参数，把参数中的所有元素追加到原列表的左侧
   * 参数必须是List类型，其余类型不支持
   */
  def func4() = {
    //正序追加
    val list1 = numList.:::(List(100,200))
    println(list1)

    //倒序追加
    val list2 = numList.reverse_:::(List(100,200))
    println(list2)

  }

  /**
   * 以集合为参数，把参数中的所有元素追加到原列表的右侧
   * 参数必须是可以是任意的不可变数据类型
   */
  def func5() = {
    val list1 = numList.++(List(100,200))
    println(list1)

    val list2 = numList.++(Set(100,200))
    println(list2)

    val list3 = numList.++(Map("name"->"tom"))
    println(list3)
  }

  /**
   * take相关的方法
   */
  def func6() = {
    //取集合中的前n个元素
    val list1 = numList.take(3)
    println(list1)
    //取集合中的后n个元素
    val list2 = numList.takeRight(3)
    println(list2)

    //从第一个元素开始获取，直到不满足条件的元素为止
    val list3 = numList.takeWhile(_<5)
    println(list3)

  }

  /**
   * 关于 drop 的方法
   */
  def func7() = {
    //移除前n个元素
    val list1 = numList.drop(3)
    println(list1)

    //移除后n个元素
    val list2 = numList.dropRight(3)
    println(list2)

    //从第一个元素开始移除，直到不满足条件的元素为止
    val list3 = numList.dropWhile(_<5)
    println(list3)
  }

  /**
   * map
   *    1.map之前是什么类型，map之后还是什么
   *    2.map之后元素的数量与map之前元素的数量完全一致
   *    3.唯一变化的是元素的内容
   */
  def func8() = {
    val list1 = numList.map(_*10)
    println(list1)
  }

  /**
   * flatten 扁平化
   */
  def func9() = {

    val strList = List(Array("apple","banana","peach"),Array("monkey","tiger","lion"))

    val list1 = strList.flatten
    println(list1)

  }

  /**
   * flatMap
   *  先做map 再做 flatten
   */
  def func10() = {
    val strList = List("apple,banana,peach","monkey,tiger,lion")

    val list1 = strList.map(_.split(","))
    println(list1)
    println(list1.flatten)

    val list2 = strList.flatMap(_.split(","))
    println(list2)

  }

  /**
   * map和foreach都是对集合中的每个元素进行操作
   * map有返回值的可以接收进行后续的处理
   * foreach没有返回值，执行完就结束了
   */
  def func11() = {
    val list1 = numList.map(_*10)
    println(list1)
    numList.foreach(println)
  }

  /**
   * 关于集合的拆分
   */
  def func12() = {

    //按条件拆分
    val list1 = numList.partition(_%2==0)
    println(list1)

    //按元素数量拆分
    val list2 = numList.splitAt(6)
    println(list2)

    //按照索引位置前闭后开截取集合
    val list3 = numList.slice(3,7)
    println(list3)

    //从第一个元素开始，直到第一个不满足条件的元素为止进行拆分
    val list4 = numList.span(_%2==0)
    println(list4)
  }

  /**
   * 关于拉链的方法
   */
  def func13() = {
    //两个集合可以把相同索引位置的元素组成键值对，以新集合形式返回；新集合的长度以原集合中最短的为主
    val keyList = List("name","age","gender")
    val valueList = List("tom","10","男")

    val list1 = keyList.zip(valueList)
    println(list1)

    //把键值对形式的List拆成key和value两个列表
    val kvList = List(("name","tom"), ("age","10"), ("gender","男"))
    val list2 = kvList.unzip
    println(list2)

    //把三个元素的元组形式的List拆成三个列表
    val threeList = List(("name","tom","good"),("age","10","veryGood"),("gender","男","smallGood"))
    val list3 = threeList.unzip3
    println(list3)

    //对于非元组形式的集合可以携带索引进行拉链处理
    val animalList = List("tiger","lion","dog","tiger")
    val list4 = animalList.zipWithIndex
    println(list4)
  }

  /**
   * 关于排序
   */
  def func14() = {
    val strList = List("apple","pear","watermelon","pineapple","banana")

    //按照元素的默认排序规则
    val list1 = strList.sorted
    println(list1)

    //按照元素的某个属性
    val list2 = strList.sortBy(_.length)
    println(list2)

    //指定排序的规则
    val list3 = strList.sortWith(_>_)
    println(list3)

  }

  /**
   * 元素去重
   */
  def func15() = {
    val numList1 = List(3,6,3,4,5,6,5,3)
    println(numList1.distinct)
  }

  /**
   * 规约操作
   *    不管集合中有多少个元素，最终得到一个结果
   */
  //1.数字类型规约操作
  def func16() = {
    println(numList.max)
    println(numList.min)
    println(numList.sum)
    println(numList.product)
  }

  //2.boolean类型的规约操作
  def func17() = {
    //判断是否存在某个具体元素
    println(numList.contains(5))
    //判断是否存在符合条件的元素
    println(numList.exists(_<5))
    //判断是否所有元素都符合条件
    println(numList.forall(_<5))
    //判断是否是当前集合开头
    println(numList.startsWith(List(1, 2, 3)))
    //判断从指定索引位置开始是否为起始位置
    println(numList.startsWith(List(4, 5, 6),3))
    //判断是否已此集合结尾
    println(numList.endsWith(List(9, 10)))
  }

  //3.其他类型的规约操作
  def func18() = {

    val numList1 = List(1,2,3,4,5,6)

    println(numList1.reduce(_ - _))
    println(numList1.reduceLeft(_ - _))
    println(numList1.reduceRight(_ - _))

    println(numList1.fold(10)(_ - _))
    println(numList1.foldLeft(10)(_ - _))
    println(numList1.foldRight(10)(_ - _))

    println(numList1.scan(10)(_ - _))
    println(numList1.scanLeft(10)(_ - _))
    println(numList1.scanRight(10)(_ - _))
  }

  def main(args: Array[String]): Unit = {
//    createSet()
//    createMap()
//    createList()
//    func1()
//    func2()
//    func3()
//    func4()
//    func5()
//    func6()
//    func7()
//    func8()
//    func9()
//    func10()
//    func11()
//    func12()
//    func13()
//    func14()
//    func15()
//    func16()
//    func17()
    func18()
  }

}
